# - Try to find libpcap include dirs and libraries
#
# Usage of this module as follows:
#
#     find_package(PCAP)
#
# Variables used by this module, they can change the default behaviour and need
# to be set before calling find_package:
#
#  PCAP_ROOT_DIR             Set this variable to the root installation of
#                            libpcap if the module has problems finding the
#                            proper installation path.
#
# Variables defined by this module:
#
#  PCAP_FOUND                System has libpcap, include and library dirs found
#  PCAP_INCLUDE_DIR          The libpcap include directories.
#  PCAP_LIBRARY              The libpcap library (possibly includes a thread
#                            library e.g. required by pf_ring's libpcap)
#  HAVE_PF_RING              If a found version of libpcap supports PF_RING

# Download winpcap
if (WIN32)
    include(ExternalProject)
    ExternalProject_Add(
        winpcap
        PREFIX ${CMAKE_BINARY_DIR}/winpcap
        URL "https://www.winpcap.org/install/bin/WpdPack_4_1_2.zip"
        URL_MD5 "bae2236af062b0900ad1416b2c4878b9"
        CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_DIR "" INSTALL_COMMAND ""
        BUILD_BYPRODUCTS <SOURCE_DIR>/Lib/x64/wpcap.lib <SOURCE_DIR>/Lib/wpcap.lib
        # LOG_DOWNLOAD ON
    )
    ExternalProject_Get_Property(winpcap SOURCE_DIR)
    set(PCAP_ROOT_DIR ${SOURCE_DIR})
    set(PCAP_INCLUDE_DIR ${PCAP_ROOT_DIR}/Include)
    set(PCAP_LIBRARY ${PCAP_ROOT_DIR}/Lib/x64/wpcap.lib ${PCAP_ROOT_DIR}/Lib/wpcap.lib)
    message("PCAP_ROOT_DIR = ${PCAP_ROOT_DIR} INCLUDE = ${PCAP_INCLUDE_DIR}")
else()
    find_path(PCAP_ROOT_DIR
        NAMES include/pcap.h
    )

    find_path(PCAP_INCLUDE_DIR
        NAMES pcap.h
        HINTS ${PCAP_ROOT_DIR}/include
    )


    find_library(PCAP_LIBRARY
        NAMES pcap
        HINTS ${PCAP_ROOT_DIR}/lib
    )
endif()

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(PCAP DEFAULT_MSG
    PCAP_LIBRARY
    PCAP_INCLUDE_DIR
)

if (!WIN32)
    include(CheckCSourceCompiles)
    set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY})
    check_c_source_compiles("int main() { return 0; }" PCAP_LINKS_SOLO)
    set(CMAKE_REQUIRED_LIBRARIES)

    # check if linking against libpcap also needs to link against a thread library
    if (NOT PCAP_LINKS_SOLO)
        find_package(Threads)
        if (THREADS_FOUND)
            set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
            check_c_source_compiles("int main() { return 0; }" PCAP_NEEDS_THREADS)
            set(CMAKE_REQUIRED_LIBRARIES)
        endif ()
        if (THREADS_FOUND AND PCAP_NEEDS_THREADS)
            set(_tmp ${PCAP_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
            list(REMOVE_DUPLICATES _tmp)
            set(PCAP_LIBRARY ${_tmp}
                CACHE STRING "Libraries needed to link against libpcap" FORCE)
        else ()
            message(FATAL_ERROR "Couldn't determine how to link against libpcap")
        endif ()
    endif ()

    include(CheckFunctionExists)
    set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY})
    check_function_exists(pcap_get_pfring_id HAVE_PF_RING)
    set(CMAKE_REQUIRED_LIBRARIES)
endif()

mark_as_advanced(
    PCAP_ROOT_DIR
    PCAP_INCLUDE_DIR
    PCAP_LIBRARY
)
